/**
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { UseData } from './types';
import { NumberRangeProps } from '../number-range.props';
import { SetupContext, Ref } from 'vue';
import { BigNumber } from 'bignumber.js';
import { UseUtil } from './use-util';

export function UseData(
    props: NumberRangeProps,
    context: SetupContext,
    realValue: Ref<number | string | null>,
    inputValue: Ref,
    isFocus: Ref<boolean>,
    formatOptions: Ref,
    targetValue: Ref<string>,
    beginValue: Ref<number | string | null>,
    endValue: Ref<number | string | null>,
    inputBeginValue: Ref,
    inputEndValue: Ref
): UseData {
    const { isDisableOfBtn, format, getRealValue, isEmpty, _modelChanged } = UseUtil(
        props,
        context,
        realValue,
        formatOptions,
        targetValue,
        beginValue,
        endValue
    );

    /**
     * 手动输入值变化时或失去焦点时的方法
     * @param realVal 输入框中的实际数值
     * @param updateOn 更新类型，分为'change'| 'blur'
     */
    function onModelChange(realVal: any, updateOn = 'change') {
        let _resultValue = realVal;
        if (updateOn === 'change') {
            _resultValue = getRealValue(realVal);
            _modelChanged(_resultValue);
        }
    }
    /**
     * 触发微调事件时，计算结果的方法
     * @param direction 微调类型 up微增 down微减
     * @param target 点击按钮微调时元素未聚焦，手动传入target辅助定位
     */
    function compute(direction: string, target: string) {
        if (props.readonly || props.disabled || !props.editable) {
            isFocus.value = false;
            return;
        }
        const computeValue = target === 'beginValue' ? beginValue.value : endValue.value;
        if (isDisableOfBtn(direction, computeValue)) {
            let _resultValue;

            const realBigNum = new BigNumber(computeValue || 0);
            if (direction === 'up') {
                _resultValue = realBigNum.plus(Number(props.step));
            } else {
                _resultValue = realBigNum.minus(Number(props.step));
            }

            const value = _resultValue.toFixed();
            if (target === 'beginValue') {
                inputBeginValue.value = isFocus.value ? value : format(value);
            } else if (target === 'endValue') {
                inputEndValue.value = isFocus.value ? value : format(value);
            }
            _modelChanged(getRealValue(_resultValue, target), target);
        }
    }
    /**
     * 点击微增按钮时或键盘触发 ArrowUp 时执行的方法
     */
    function up(e: Event, target: string) {
        compute('up', target);
        e.stopPropagation();
    }

    /**
     * 点击微减按钮时或键盘触发 ArrowDown 时执行的方法
     */
    function down(e: Event, target: string) {
        compute('down', target);
        e.stopPropagation();
    }

    /**
     * 输入框失焦时执行的方法
     */
    function onBlurTextBox($event: Event, target: string) {
        $event.stopPropagation();
        if (props.readonly || props.disabled || !props.editable) {
            return;
        }

        if (target === 'beginValue') {
            inputBeginValue.value = format(beginValue.value);
            onModelChange(beginValue.value, 'blur');
        } else if (target === 'endValue') {
            inputEndValue.value = format(endValue.value);
            onModelChange(endValue.value, 'blur');
        }

        isFocus.value = false;
        const emitData = {
            eventTarget: targetValue.value,
            event: $event,
            beginValue: beginValue.value,
            formatBeginValue: format(beginValue.value),
            endValue: endValue.value,
            formatEndValue: format(endValue.value)
        };
        context.emit('focus', emitData);
        targetValue.value = '';
    }

    /**
     * 输入框获取焦点时执行的方法
     */
    function onFocusTextBox($event: Event, target: string) {
        $event.stopPropagation();
        if (props.readonly || props.disabled || !props.editable) {
            isFocus.value = false;
            targetValue.value = '';
            return;
        }
        targetValue.value = target;
        isFocus.value = true;

        if (target === 'beginValue') {
            inputBeginValue.value = isEmpty(beginValue.value) ? '' : !props.showZero && beginValue.value === '0' ? '' : beginValue.value;
        } else if (target === 'endValue') {
            inputEndValue.value = isEmpty(endValue.value) ? '' : !props.showZero && endValue.value === '0' ? '' : endValue.value;
        }
        const emitData = {
            eventTarget: targetValue.value,
            event: $event,
            beginValue: beginValue.value,
            formatBeginValue: format(beginValue.value),
            endValue: endValue.value,
            formatEndValue: format(endValue.value)
        };
        context.emit('focus', emitData);
    }

    /**
     * 输入框的input事件
     */
    function onInput($event: Event) {
        $event.stopPropagation();
        const value = ($event.target as HTMLTextAreaElement)?.value;

        if (targetValue.value === 'beginValue') {
            inputBeginValue.value = value;
        } else if (targetValue.value === 'endValue') {
            inputEndValue.value = value;
        }
        onModelChange(value, 'change');
    }

    /**
     * 焦点状态下键盘监听事件
     */
    function onKeyDown(e: KeyboardEvent) {
        if (e.key === 'ArrowDown') {
            e.preventDefault();
            down(e, targetValue.value);
        }

        if (e.key === 'ArrowUp') {
            e.preventDefault();
            up(e, targetValue.value);
        }

        e.stopPropagation();
    }
    return {
        onModelChange,
        up,
        down,
        onBlurTextBox,
        onFocusTextBox,
        onInput,
        onKeyDown
    };
}
